Usually you will want to leave the Linux kernel alone except when performing a major
upgrade, installing a new networking component (such as NFS or NIS), or installing a new
device driver that has special kernel requirements. The details of the process used to
install the kernel drivers are usually supplied with the software. Because this isn't
always the case, though, this chapter should give you a good idea of the general process
for working with the kernel.
Don't modify the kernel without knowing what you are doing. If you damage the source code or configuration information, your kernel may be unusable, and in the worst cases, your filesystem may be affected. Take care and follow instructions carefully. keep in mind that this chapter only covers the basics of kernel manipulation.
The several versions of Linux in common use have a few inconsistencies between them.
For that reason, the exact instructions supplied in the following sections may not work
with your version of Linux. The general approach is the same, however, and only the
directory or utility names may be different. Most versions of Linux supply documentation
that lists the recompilation process and the locations of the source code and compiled
programs.
Before doing anything with the kernel or utilities, make sure you have a good set of emergency boot disks and a complete backup on tape or floppy disk. Although the process of modifying the kernel is not difficult, it does cause problems every now and again that can leave you stranded without a working system. Boot disks are the best way to recover, so make at least one extra set.
Because the kernel is compiled with the C compiler supplied as part of Linux, the
latter part of this chapter looks at the C compiler and its flags and how you can use it
to your advantage. This information isn't meant to be a complete reference to the C
system, of course, but it should be useful for some basic manipulations you may require
when modifying the kernel (or any other source code compiled by C).
Linux is a dynamic operating system. New releases of the kernel or parts of the
operating system that can be linked into the kernel are made available at regular
intervals to users. Whether you want to upgrade to the new releases usually depends on the
features or bug fixes that the new release offers. You will probably have to relink the
kernel when you add new software, unless the software is loaded as a utility or device
driver.
Avoid upgrading your system with every new release, for a couple of reasons. The most
common problem with constant upgrades is that you may be stuck with a new software package
that causes backward compatibility problems with your existing system or that has a major
problem with it. Most new releases of software wipe out existing configuration
information, so you will have to reconfigure the packages that are being installed from
scratch. Also, the frequency with which new releases are made available is so high that
you can probably spend more time loading and recompiling kernels and utilities than using
the system. Read the release notes carefully to ensure that the release is worth the
installation time and trouble. Remember that few installations proceed smoothly!
The best advice is to upgrade only once or twice a year, and only when there is a new
feature or enhancement that will make a significant difference to the way you use Linux.
It's tempting to always have the latest and newest versions of the operating system, but
there is a lot to be said for having a stable, functioning operating system, too.
If you do upgrade to a new release, bear in mind that you don't have to upgrade
everything. The last few Linux releases have changed only about five percent of the
operating system with each new major package upgrade. Instead of replacing the entire
system, just install those parts that will have a definite effect, such as the kernel,
compilers and their libraries, and frequently used utilities. This method saves time and
reconfiguration.
Upgrading, replacing, or adding new code to the kernel is usually a simple process. You
obtain the source for the kernel, make any configuration changes, compile it, and then
place it in the proper location on the filesystem to run the system properly. The process
is often automated for you by a shell script or installation program, and some upgrades
are completely automated with no need to do anything more than start the upgrade utility.
Kernel sources for new releases of Linux are available from CD-ROM distributions, FTP
sites, user groups, and many other locations. Most kernel versions are numbered with a
version and a patch level, so you see kernel names like 1.12.123 where 1 is the major
release, 12 is the minor version release, and 123 is the patch number. Most kernel source
sites maintain several versions simultaneously, so check through the source directories
for the latest version of the kernel.
Patch releases are sometimes numbered differently, and do not require the entire source
of the kernel to install. In most cases, the patch overlays a section of existing source
code, and you only need to recompile the kernel to install the patch. Patches are released
quite frequently.
Most kernel source programs are maintained as a gzipped tar file. Unpack the files into
a subdirectory of /usr/src, which is where most of the source code is kept for Linux. Some
versions of Linux keep other directories for the kernel source, so you may want to check
any documentation supplied with the system or look for a README file in the /usr/src
directory for more instructions.
Often, unpacking the gzipped tar file in /usr/src creates a subdirectory called
/usr/src/linux, which can overwrite your last version of the kernel source. Before
starting the unpacking process, rename or copy any existing /usr/src/linux (or whatever
name is used with the new kernel) file so you have a backup version in case of problems.
After unpacking the kernel source, you need to create two symbolic links to the
/usr/include directory (if they are not created already or set by the installation
procedure). Usually, the link commands required are the following:
ln -sf /usr/src/linux/include/linux /usr/include/linux ln -sf /usr/src/linux/include/asm /usr/include/asm
If the directory names are different with your version of Linux, substitute them for
/usr/src/linux. Without these links, the upgrade or installation of a new kernel cannot
proceed.
After ungzipping and untarring the source code and establishing the links, you can
begin the compilation process. You must have a version of gcc or g++ (the GNU C and C++
compilers) or some other compatible compiler available for the compilation. You may have
to check with the source code documentation to make sure you have the correct versions of
the compilers; occasionally new kernel features are added that are not supported by older
versions of gcc or g++.
Check the file /usr/src/linux/Makefile (or whatever path Makefile is in with your
source distribution). This file has a line that defines the ROOT_DEV, the device that is
used as the root filesystem when Linux boots. Usually the line looks like the following:
ROOT_DEV = CURRENT
If you have any other value, make sure it is correct for your filesystem configuration.
If the Makefile has no value, set it as shown in the preceding line.
The compilation process begins with you changing to the /usr/src/linux directory and
issuing the command
make config
which invokes the make utility for the C compiler. The process may be slightly
different for some versions of Linux, so check any release or installation notes supplied
with the source code.
The config program issues a series of questions and prompts you to answer to indicate
any configuration issues that need to be completed before the compilation begins. These
questions may be about the type of disk drive you are using, the CPU, any partitions, or
other devices like CD-ROMs. Answer the questions as well as you can. If you are unsure,
choose the default values or the one that makes the most sense. The worst case is that you
will have to redo the process if the system doesn't run properly. (You do have an
emergency boot disk ready, don't you?)
Next, you have to set all the source dependencies. This step is commonly skipped and can cause a lot of problems if is not performed for each software release. Issue the following command:
make dep
If the software you are installing does not have a dep file, check the release or
installation notes to ensure that the dependencies are correctly handled by the other
steps.
Now you can finally compile the new kernel. The command to start the process is
make Image
which compiles the source code and leaves the new kernel image file in the current
directory (usually /usr/src/linux). If you want to create a compressed kernel image, you
can use the following command:
make zImage
Not all releases or upgrades to the kernel support compressed image compilation.
The last step in the process is to copy the new kernel image file to the boot device or a boot floppy disk. To place the kernel on a floppy disk, use the following command:
cp Image /dev/fd0
Use a different device driver as necessary to place the kernel elsewhere on the hard
drive filesystem. Alternatively, if you plan to use LILO to boot the operating system, you
can install the new kernel by running a setup program or the utility /usr/lilo/lilo. Don't
copy the new kernel over your old boot disk's kernel. If the new kernel doesn't boot, you
may have to use the older boot disk to restart your system.
Now all that remains is to reboot the system and see whether the new kernel loads
properly. If you have any problems, boot from a floppy disk, restore the old kernel, and
start the process again. Check documentation supplied with the release source code for any
information about problems you may encounter or steps that may have been added to the
process.
You may want to link in new device drivers or special software to the kernel without
going through the upgrade process of the kernel itself. This procedure is often necessary
when you add a new device like a multiport board or an optical drive that should be loaded
during the boot process. Alternatively, you may be adding special security software that
must be linked into the kernel.
Add-in kernel software usually has installation instructions provided, but the general
process is to locate the source in a directory that the kernel recompilation process can
find (such as /usr/src). Instructing the make utility to add the new code to the kernel
may require modifications to the Makefile. Either you or an installation script can make
these modifications. Some software has its own Makefile supplied for this reason.
Then, begin the kernel recompilation with the new software added in to the load. The
process is the same as shown in the preceding section, with the kernel installed in the
boot location or set by LILO. Typically, the entire process takes about 10 minutes and is
quite troublefree unless the vendor of the kernel modification did a sloppy job. Make sure
that the source code provided for the modification works with your version of the Linux
kernel.
Most of the software on a Linux system is set to use shared libraries (a set of
subroutines used by many programs). When the message
Incompatible library version
appears on-screen after you upgrade the system and you try to execute a utility, it
means that the libraries have been updated and need to be recompiled. Most libraries are
backwards-compatible, so existing software should work properly even after a library
upgrade.
Library upgrades are less frequent than kernel upgrades and can be found in the same
places. There are usually documents that guide you to the latest version of a library, or
there may be a file explaining which libraries are necessary with new versions of the
operating system kernel. Most library upgrades are gzipped tar files, and the process for
unpacking them is the same as for kernel source code except the target directories are
usually /lib, /usr/lib, and /usr/include. Usually, any files that have the extension .a or
.aa go in the /usr/lib directory. Shared library image files, which have the format
libc.so.version, are installed into /lib.
You may have to change symbolic links within the filesystem to point to the latest
version of the library. For example, if you were running library version libc.so.4.4.1 and
upgraded to libc.so.4.4.2, you must alter the symbolic link set in /lib to this file. The
command would be
ln -sf /lib/libc/so/4/4/1 /lib/libc.so.4
where the last name in the link command is the name of the current library file in
/lib. Your library name may be different, so check the directory and release or
installation notes first.
You will also have to change the symbolic link for the file libm.so.version in the same
manner. Do not delete the symbolic links; if you do, all programs that depend on the
shared library (including ls) will be unable to function.
Linux uses a C compiler for every compilation of the kernel (and most utilities, too).
The C compiler that is available for all versions of Linux is the GNU C compiler,
abbreviated gcc. This compiler was created under the Free Software Foundation's
programming license and is therefore freely distributable. The GNU C Compiler that is
packaged with the Slackware Linux distribution is a fully functional ANSI C compatible
compiler. If you are familiar with a C compiler on a different operating system or
hardware platform, you will be able to learn gcc very quickly.
The GCC compiler is invoked by passing it a number of options and one or more filenames. The basic syntax for gcc is as follows:
gcc [options] [filenames]
The operations specified by the command line options are performed on each of the files
that are on the command line. There are well over 100 compiler options that can be passed
to gcc. You will probably never use most of these options, but you will use some of them
on a regular basis.
Many of the gcc options consist of more than one character. For this reason, you must
specify each option with its own hyphen. You cannot group options after a single hyphen as
you can with most Linux commands. For example, the following two commands are not the
same:
gcc -p -g test.c
gcc -pg test.c
The first command tells gcc to compile test.c with profile information (-p) and also to
store debugging information with the executable (-g). The second command just tells gcc to
compile test.c with profile information for the gprof command (-pg).
When you compile a program using gcc without any command line options, it creates an
executable file (assuming that the compile was successful) and calls it a.out. To specify
a name other than a.out for the executable file, you use the -o compiler option. For
example, to compile a C program file named count.c into an executable file named count,
use the following command:
gcc -o count count.c
As shown in the preceding example, the executable file name must occur directly after
the -o on the command line.
Other compiler options enable you to specify how far you want the compile to proceed.
The -c option tells gcc to compile the code into object code and to skip the assembly and
linking stages of the compile. This option is used quite often because it makes the
compilation of multifile C programs faster and easier to manage. Object code files that
are created by gcc have a .o extension by default.
The -S compiler option tells gcc to stop the compile after it has generated the
assembler files for the C code. Assembler files that are generated by gcc have a .s
extension by default. The -E option instructs the compiler to only perform the
preprocessing compiler stage on the input files. When this option is used, the output from
the preprocessor is sent to the standard output rather than being stored in a file.
When you compile C code with gcc, it tries to compile the code in the least amount of
time and also tries to create compiled code that is easy to debug. Making the code easy to
debug means that the sequence of the compiled code is the same as the sequence of the
source code and no code gets optimized out of the compile. There are many options that you
can use to tell gcc to create smaller, faster executable programs at the cost of compile
time and ease of debugging. Of these options, the two that you will use most are the -O
and the -O2 options.
The -O option tells gcc to perform basic optimizations on the source code. These
optimizations make the code run faster in most cases. The -O2 option tells gcc to make the
code as fast and small as it can. The -O2 option causes the compilation speed to be slower
than it is when using the -O option, but it typically results in code that executes more
quickly.
In addition to the -O and -O2 optimization options, you can use a number of lower-level
options to make the code faster. These options are very specific and should only be used
if you fully understand the effect of these options on the compiled code. For a detailed
description of these options, refer to the gcc man page.
The gcc compiler supports several debugging and profiling options. Of these options,
the two that you are most likely to use are the -g option and the -pg option.
The -g option tells GCC to produce debugging information that the GNU debugger (gdb)
can use to help you to debug your program. The gcc program provides a feature that many
other C compilers do not have. With gcc, you can use the -g option in conjunction with the
-O option (which generates optimized code). This feature can be very useful if you are
trying to debug code that is as close as possible to what will exist in the final product.
When you are using these two options together, be aware that gcc will probably change some
of the code that you have written when gcc optimizes the code.
The -pg option tells gcc to add extra code to your program that, when executed,
generates profile information that the gprof program uses to display timing information
about your program.
Linux includes the GNU debugging program called gdb. You can use gdb debugger to debug
C and C++ programs. It enables you to see the internal structure or the memory that a
program is using while it is executing. This debugging program enables you to perform the
following functions:
When you start gdb, you can specify a number of options on the command line. You will
probably run gdb most often with this command:
gdb filename
When you invoke gdb in this way, you are specifying the executable file that you want
to debug. You can also tell gdb to inspect a core file that was created by the executable
file being examined or attach gdb to a currently running process. To get a listing and
brief description of each of these other options, refer to the gdb man page or type gdb -h
at the command line.
To get gdb to work properly, you must compile your programs so that
the compiler generates debugging information. The debugging information that is generated
contains the types for each of the variables in your program as well as the mapping
between the addresses in the executable program and the line numbers in the source code.
The gdb debugging program uses this information to relate the executable code to the
source code. To compile a program with the debugging information turned on, use the -g
compiler option.
Recompiling the kernel source and adding new features to the kernel proceeds smoothly as long as you know what you are doing. Don't let the process scare you, but always keep boot disks on hand. Follow instructions wherever available as most new software has special requirements for linking into the kernel or replacing existing systems.